
#import "XLayerController.h"

#import "XLog.h"
#import "XMacro.h"
#import "UIColor+X.h"
#import "UIView+X.h"


NSInteger const TAG_MASK_NONE                       = 0x0;
NSInteger const TAG_MASK_BACKGROUNDFOCUS            = 0x2000;
NSInteger const TAG_MASK_BACKGROUNDCLOSE            = 0x4000;


UIWindow                *g_Container = nil;
UIControl               *g_ContainerCtrl = nil;
XLayerController        *g_LayerController = nil;


@interface XLayerController ()

@end


@implementation XLayerController


/**
 * 默认单例对象
 * @result       MessageController 单例对象
 */
+ (id)si {
    @synchronized (self) {
        if (nil == g_LayerController) {
            g_LayerController = [[XLayerController alloc] init];
        }
    }
    
    return g_LayerController;
}


/**
 * 初始化
 * @result       MessageController 对象
 */
- (id)init {
    self = [super init];
    if (self) {
        
    }
    
    return self;
}


/**
 * 背景点击响应
 * @param        sender，背景 UIControl 对象
 * @result
 */
- (void)onBackgroundTouch:(id)sender {
    // 获取最上面的层
    UIView *lastLayer = [g_ContainerCtrl.subviews lastObject];
    
    // 根据最上面的层是否响应背景关闭，决定是否执行关闭操作
    if (lastLayer.tag & TAG_MASK_BACKGROUNDCLOSE) {
        [self removeLayer:lastLayer];
    }
}


/**
 * 添加消息显示层
 * @param        layer，消息显示层
 * @param        focus，聚焦（含有黑色背景）
 * @param        bgClose，点击背景关闭
 * @result
 */
- (void)addLayer:(UIView *)layer withFocus:(BOOL)focus andBackgroundClose:(BOOL)bgClose {
    // 根据传入的状态，初始化标志位
    layer.tag = layer.tag & 0xFFF;
    layer.tag |= focus ? TAG_MASK_BACKGROUNDFOCUS : TAG_MASK_NONE;
    layer.tag |= bgClose ? TAG_MASK_BACKGROUNDCLOSE : TAG_MASK_NONE;
    
    UIView *vLayer = nil;
    // 初始化消息层
    if (nil == g_Container) {
        // 覆盖整个屏幕的Window
        g_Container = [[UIWindow alloc] init];
        CGRect r = [[UIScreen mainScreen] bounds];
        g_Container.frame = r;
        g_Container.windowLevel = UIWindowLevelStatusBar;
        [g_Container makeKeyAndVisible];
        // 覆盖整个屏幕的透明的触摸层 加入到window中
        r = g_Container.frame;
        r.origin = CGPointZero;
        g_ContainerCtrl = [[UIControl alloc] initWithFrame:r];
        g_ContainerCtrl.backgroundColor = [UIColor clearColor];
        [g_ContainerCtrl addTarget:self
                 action:@selector(onBackgroundTouch:)
       forControlEvents:UIControlEventTouchUpInside];
        
        [g_Container addSubview:g_ContainerCtrl];
    }
    else if (g_ContainerCtrl.subviews.count > 0) {
        // 找找看是否有相同的在里面
        for (UIView *vSub in g_ContainerCtrl.subviews) {
            if ([vSub isEqual:layer]) {
                vLayer = vSub;
                break;
            }
        }
        
        // 若将要加入的层已经存在，但不是最上层，则将其提到最上层
        UIView *lastLayer = [g_ContainerCtrl.subviews lastObject];
        if (vLayer && ![vLayer isEqual:lastLayer]) {
            lastLayer.alpha = 0.0f;
            [g_ContainerCtrl bringSubviewToFront:vLayer];
        }
    }
    if (vLayer == nil) {
        // 没有找到已经存在的layer
        [g_ContainerCtrl addSubview:layer];
        vLayer = layer;
    }
    
    // 动画处理当前窗口的淡入
    g_ContainerCtrl.backgroundColor = [UIColor colorWithHex:0x000000 andAlpha:0.0];
    vLayer.alpha = 0.0f;
    [UIView animateWithDuration:0.35f  animations:^{
        if (layer.tag & TAG_MASK_BACKGROUNDFOCUS) {
            g_ContainerCtrl.backgroundColor = [UIColor colorWithHex:0x000000 andAlpha:0.5];
        }
        vLayer.alpha = 1.0f;
    } completion:^(BOOL finished) {
        
    }];
}


/**
 * 移除消息显示层
 * @param        layer，消息显示层
 * @result
 */
- (void)removeLayer:(UIView *)layer {
    // 若还有窗口，则将下一层的窗口显示
    
    if (g_ContainerCtrl.subviews.count > 1) {
        layer.alpha = 0.0f;
        
        NSUInteger uIndex = g_ContainerCtrl.subviews.count - 2;
        UIView *nextLayer = [g_ContainerCtrl.subviews objectAtIndex:uIndex];
        if (nextLayer != layer) {
            // 必须不为当前的
            [g_ContainerCtrl bringSubviewToFront:nextLayer];
            
            // 动画处理淡入
            g_ContainerCtrl.backgroundColor = [UIColor colorWithHex:0x000000 andAlpha:0.0];
            nextLayer.alpha = 0.0f;
            [UIView animateWithDuration:0.35f animations:^{
                if (nextLayer.tag & TAG_MASK_BACKGROUNDFOCUS) {
                    g_ContainerCtrl.backgroundColor = [UIColor colorWithHex:0x000000 andAlpha:0.5];
                }
                nextLayer.alpha = 1.0f;
            } completion:^(BOOL finished) {
            }];
        }
        
        // 移除当前窗口
        [layer removeFromSuperview];
    }
    else {
        // 动画处理当前窗口的淡出
        [UIView animateWithDuration:0.35f animations:^{
            g_ContainerCtrl.backgroundColor = [UIColor colorWithHex:0x000000 andAlpha:0.0];
            layer.alpha = 0.0f;
        } completion:^(BOOL finished) {
            // 移除当前窗口
            [layer removeFromSuperview];
            if (g_ContainerCtrl.subviews.count == 0) {
                [g_ContainerCtrl removeFromSuperview];
                g_ContainerCtrl = nil;
                
                [g_Container resignKeyWindow];
                g_Container = nil;
            }
        }];
    }
}


/**
 * 最上面的层
 * @result       最上面的层
 */
- (UIView *)topLayer {
    return [g_ContainerCtrl.subviews lastObject];
}


/**
 * 添加消息显示层
 * @param        layer，消息显示层
 * @result
 */
+ (void)addLayer:(UIView *)layer {
    VERIFY_OBJECT(layer, none);
    XLayerController *ctrl = [XLayerController si];
    if (![layer isEqual:[ctrl topLayer]]) {
        // 只有不与顶层相同的Layer才能够加入
        [ctrl addLayer:layer withFocus:YES andBackgroundClose:NO];
    }
}


/**
 * 添加消息显示层
 * @param        layer，消息显示层
 * @param        focus，聚焦（含有黑色背景）
 * @param        bgClose，点击背景关闭
 * @result
 */
+ (void)addLayer:(UIView *)layer withFocus:(BOOL)focus andBackgroundClose:(BOOL)bgClose {
    VERIFY_OBJECT(layer, none);
    XLayerController *ctrl = [XLayerController si];
    if (![layer isEqual:[ctrl topLayer]]) {
        // 只有不与顶层相同的Layer才能够加入
        [ctrl addLayer:layer withFocus:focus andBackgroundClose:bgClose];
    }
}


/**
 * 移除消息显示层
 * @param        layer，消息显示层
 * @result
 */
+ (void)removeLayer:(UIView *)layer {
    VERIFY_OBJECT(layer, none);
    XLayerController *ctrl = [XLayerController si];
    [ctrl removeLayer:layer];
}


@end

